﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Xml.Linq;
using Orchard;
using Orchard.Localization;
using Orchard.Security;
using Orchard.UI.Admin;
using Orchard.UI.Navigation;
using Orchard.UI.Notify;
using Bootstrap.Services;

namespace Bootstrap.Controllers
{

    public class FeatureViewModel {
        public string Name { get; set; }
        public string DisplayName { get; set; }
        public bool Enabled { get; set; }
    }

    
    public class VariableValueViewModel {
        public string Name { get; set; }
        public string Value { get; set; }
    }

    public class SettingValueViewModel
    {
        public string Name { get; set; }
        public string DisplayName { get; set; }
        public bool HasChoices { get; set; }
        public string[] Choices { get; set; }
        public bool IsSwitch { get; set; }
        public string Value { get; set; }
    }

    public class BootstrapConfigureViewModel {
        public ILookup<string, FeatureViewModel> Features { get; set; }
        public ILookup<string, VariableValueViewModel> Variables { get; set; }
        public ILookup<string, SettingValueViewModel> Settings { get; set; }
    }

    [Admin]
    public class AdminController : Controller
    {
        private readonly IOrchardServices _services;
        private readonly IBootstrapSettingsService _settings;
        private readonly IBootstrapBuildService _builder;

        public Localizer T { get; set; }

        public AdminController(
            IOrchardServices services,
            IBootstrapSettingsService settings,
            IBootstrapBuildService builder
        ) {
            _services = services;
            _settings = settings;
            _builder = builder;
            T = NullLocalizer.Instance;
        }

        public ActionResult Settings() {
            var settings =
                _settings
                    .Settings()
                    .Where(x => x.Category.Priority != 0 && x.DisplayPriority != 0)
                    .OrderByDescending(x => x.Category.Priority)
                    .ThenBy(x => x.DisplayPriority)
                    .ToLookup(
                        k => k.Category.Name,
                        v => new SettingValueViewModel()
                        {
                            Name = v.Name,
                            DisplayName = v.DisplayName,
                            Value = _settings.GetSetting(v.Name),
                            IsSwitch = v.IsSwitch,
                            HasChoices = v.HasChoices,
                            Choices = v.Choices
                        }
                    );

            return View(settings);
        }

        [HttpPost, ActionName("Settings")]
        public ActionResult PostSettings()
        {
            var settings =
                _settings
                    .Settings()
                    .Where(x => x.Category.Priority != 0 && x.DisplayPriority != 0)
                    .ToDictionary(
                        k => k.Name,
                        v => new SettingValueViewModel()
                        {
                            Name = v.Name,
                            DisplayName = v.DisplayName,
                            Value = _settings.GetSetting(v.Name),
                            IsSwitch = v.IsSwitch,
                            HasChoices = v.HasChoices,
                            Choices = v.Choices
                        }
                    );
            foreach (var setting in settings)
            {
                var nValue = Request.Form[setting.Key];
                if (setting.Value.IsSwitch)
                {
                    nValue = nValue.Split(',')[0];
                }
                else if (setting.Value.HasChoices)
                {
                    if (!setting.Value.Choices.Contains(nValue))
                        nValue = setting.Value.Value;
                }
                if (setting.Value.Value != nValue)
                    _settings.SetSetting(setting.Key, nValue);

            }

            //We're now ALWAYS building to disk...
            //In my projects using this theme, the build overhead is steep. 4+ms for each stage from the database, plus 2+ms for the build.
            //That may not sound like much, but in load testing it really adds up. (14+ms per request)
            _builder.BuildToFile();

            _services.Notifier.Add(NotifyType.Information, T("Settings Saved"));
            return RedirectToAction("Settings");
        }

        public ActionResult Features() {
            var featureList =
                _settings
                    .Features()
                    .Where(
                        x => x.Category.Priority != 0 && x.DisplayPriority != 0
                    )
                    .OrderByDescending(x => x.Category.Priority)
                    .ThenByDescending(x => x.DisplayPriority)
                    .ToLookup(
                        k => k.Category.Name,
                        v => new FeatureViewModel()
                        {
                            DisplayName = v.DisplayName,
                            Name = v.Name,
                            Enabled = _settings.IsEnabled(v.Name)
                        }
                    );

            return View(featureList);
        }

        [HttpPost, ActionName("Features")]
        public ActionResult PostFeatures()
        {
            var featureList =
                _settings
                    .Features()
                    .Where(
                        x => x.Category.Priority != 0 && x.DisplayPriority != 0
                    )
                    .ToDictionary(
                        k => k.Name,
                        v => new FeatureViewModel()
                        {
                            DisplayName = v.DisplayName,
                            Name = v.Name,
                            Enabled = _settings.IsEnabled(v.Name)
                        }
                    );
            foreach (var feature in featureList)
            {
                var nValue = false;
                if (!bool.TryParse(Request.Form[feature.Key].Split(',')[0], out nValue))
                {
                    continue;
                }
                if (feature.Value.Enabled != nValue)
                    _settings.SetFeature(feature.Key, nValue);
            }
            _builder.BuildToFile();
            _services.Notifier.Add(NotifyType.Information, T("Settings Saved"));
            return RedirectToAction("Features");
        }

        public ActionResult Variables() {
            var variables =
                _settings
                    .Variables()
                    .Where(x => x.Section.Priority != 0 && x.DisplayPriority != 0)
                    .OrderByDescending(x => x.Section.Category.Priority)
                    .ThenByDescending(x => x.Section.Priority)
                    .ThenByDescending(x => x.DisplayPriority)
                    .ToLookup(
                        k => k.Section.Name,
                        v => new VariableValueViewModel()
                        {
                            Name = v.Name,
                            Value = _settings.GetValue(v.Name)
                        }
                    );


            return View(variables);
        }

        [HttpPost, ActionName("Variables")]
        public ActionResult PostVariables() {
            var variables =
                _settings
                    .Variables()
                    .Where(x => x.Section.Priority != 0 && x.DisplayPriority != 0)
                    .ToDictionary(
                        k => k.Name,
                        v => new VariableValueViewModel()
                        {
                            Name = v.Name,
                            Value = _settings.GetValue(v.Name)
                        }
                    );
            foreach (var variable in variables)
            {
                var nValue = Request.Form[variable.Key];
                if (variable.Value.Value != nValue)
                    _settings.SetValue(variable.Key, nValue);

            }
            _builder.BuildToFile();
            _services.Notifier.Add(NotifyType.Information, T("Settings Saved"));
            return RedirectToAction("Variables");
        }

        public ActionResult Import() {
            return View();
        }

        [HttpPost, ActionName("Import")]
        public ActionResult PostImport(HttpPostedFileBase source)
        {
            var src = XDocument.Load(source.InputStream);
            _settings.Import(src);
            _services.Notifier.Add(NotifyType.Information, T("Import Complete."));
            return RedirectToAction("Import");
        }

        public ActionResult Export() {
            var stream = new MemoryStream();
            var xml = _settings.Export();
            xml.Save(stream);
            stream.Position = 0;
            return File(stream, "application/xml", "bootstrap.xml");
        }

        //public ActionResult Configure() {
        //    var featureList =
        //        _settings
        //            .Features()
        //            .Where(
        //                x => x.Category.Priority != 0 && x.DisplayPriority != 0 
        //            )
        //            .OrderByDescending(x => x.Category.Priority)
        //            .ThenByDescending(x => x.DisplayPriority)
        //            .ToLookup(
        //                k => k.Category.Name,
        //                v => new FeatureViewModel() {
        //                    DisplayName = v.DisplayName, 
        //                    Name = v.Name, 
        //                    Enabled = _settings.IsEnabled(v.Name)
        //                }
        //            );

        //    var variables =
        //        _settings
        //            .Variables()
        //            .Where(x => x.Category.Priority != 0 && x.DisplayPriority != 0)
        //            .OrderByDescending(x => x.Category.Priority)
        //            .ThenByDescending(x => x.DisplayPriority)
        //            .ToLookup(
        //                k => k.Category.Name,
        //                v => new VariableValueViewModel() {
        //                    Name = v.Name, 
        //                    Value = _settings.GetValue(v.Name)
        //                }
        //            );
        //    var settings =
        //        _settings
        //            .Settings()
        //            .Where(x => x.Category.Priority != 0 && x.DisplayPriority != 0)
        //            .OrderByDescending(x => x.Category.Priority)
        //            .ThenBy(x => x.DisplayPriority)
        //            .ToLookup(
        //                k => k.Category.Name,
        //                v => new SettingValueViewModel() {
        //                    Name = v.Name,
        //                    DisplayName = v.DisplayName,
        //                    Value = _settings.GetSetting(v.Name),
        //                    IsSwitch = v.IsSwitch,
        //                    HasChoices = v.HasChoices,
        //                    Choices = v.Choices
        //                }
        //            );

        //    var model = new BootstrapConfigureViewModel {
        //        Features = featureList,
        //        Variables = variables,
        //        Settings =  settings
        //    };

        //    return View(model);
            
        //}
        //[HttpPost, ActionName("Configure")]
        //public ActionResult PostConfigure() {
        //    var featureList =
        //        _settings
        //            .Features()
        //            .Where(
        //                x => x.Category.Priority != 0 && x.DisplayPriority != 0
        //            )
        //            .ToDictionary(
        //                k => k.Name,
        //                v => new FeatureViewModel() {
        //                    DisplayName = v.DisplayName,
        //                    Name = v.Name,
        //                    Enabled = _settings.IsEnabled(v.Name)
        //                }
        //            );

        //    var variables =
        //        _settings
        //            .Variables()
        //            .Where(x => x.Category.Priority != 0 && x.DisplayPriority != 0)
        //            .ToDictionary(
        //                k => k.Name,
        //                v => new VariableValueViewModel() {
        //                    Name = v.Name, 
        //                    Value = _settings.GetValue(v.Name)
        //                }
        //            );
        //    var settings =
        //        _settings
        //            .Settings()
        //            .Where(x => x.Category.Priority != 0 && x.DisplayPriority != 0)
        //            .ToDictionary(
        //                k => k.Name,
        //                v => new SettingValueViewModel()
        //                {
        //                    Name = v.Name,
        //                    DisplayName = v.DisplayName,
        //                    Value = _settings.GetSetting(v.Name),
        //                    IsSwitch = v.IsSwitch,
        //                    HasChoices = v.HasChoices,
        //                    Choices = v.Choices
        //                }
        //            );

        //    foreach (var feature in featureList) {
        //        var nValue = false;
        //        if (!bool.TryParse(Request.Form[feature.Key], out nValue)) {
        //            continue;
        //        }
        //        if (feature.Value.Enabled != nValue)
        //            _settings.SetFeature(feature.Key, nValue);
        //    }

        //    foreach (var variable in variables) {
        //        var nValue = Request.Form[variable.Key];
        //        if (variable.Value.Value != nValue)
        //            _settings.SetValue(variable.Key, nValue);
                
        //    }

        //    foreach (var setting in settings) {
        //        var nValue = Request.Form[setting.Key];
        //        if (setting.Value.IsSwitch) {
        //            nValue = nValue.Split(',')[0]; 
        //        }
        //        else if (setting.Value.HasChoices) {
        //            if (!setting.Value.Choices.Contains(nValue))
        //                nValue = setting.Value.Value;
        //        }
        //        if (setting.Value.Value != nValue)
        //            _settings.SetSetting(setting.Key, nValue);
                
        //    }
        //    _services.Notifier.Add(NotifyType.Information, T("Settings Saved"));
        //    return RedirectToAction("Configure");
        //}
    }
}
